package io.itit.ecp.admin.provide.renderer;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Pair;
import com.alibaba.fastjson.serializer.ValueFilter;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.provide.action.resp.CarbonSinkDataResp;
import io.itit.ecp.admin.provide.filter.ICarbonSinkDataFilter;
import io.itit.ecp.admin.provide.helper.CarbonSinkFactorHelper;
import io.itit.ecp.admin.server.entity.CarbonSinkDataEntity;
import io.itit.ecp.admin.server.entity.SceneProjectEntity;
import io.itit.ecp.admin.server.entity.extend.CarbonSinkDataExtEntity;
import io.itit.ecp.admin.server.service.ICarbonSinkDataService;
import io.itit.ecp.admin.server.service.ISceneProjectService;
import io.itit.grass.common.utils.Y666Utils;
import io.itit.grass.estelle.starter.parse.AbstractParseRenderer;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * @Author：Roy
 * @Description：碳汇数据导入解析器
 * @Date：Create by 2023-12-01 10:45:08
 */
@Scope("prototype")
@Component(CarbonSinkDataRenderer.ENTITY_NAME)
public class CarbonSinkDataRenderer extends AbstractParseRenderer<CarbonSinkDataExtEntity> {

    public static final String ENTITY_NAME = "carbonSinkDataRenderer";

    @Resource
    private ICarbonSinkDataService carbonSinkDataService;

    @Resource
    private ISceneProjectService sceneProjectService;

    private Map<String, String> projectMap;

    private Set<String> dataSet;

    private Set<String> keySet = new HashSet<>();

    private Map<String, BigDecimal> factorMap = new HashedMap();

    @Override
    public String entityName() {
        return ENTITY_NAME;
    }

    @Override
    public Class<CarbonSinkDataExtEntity> getClazz() {
        return CarbonSinkDataExtEntity.class;
    }

    @Override
    public ValueFilter getValueFilter() {
        return new ICarbonSinkDataFilter.CarbonSinkDataUploadFilter();
    }

    @Override
    public void processBefore() {
        projectMap = sceneProjectService.lambdaQuery()
                .list()
                .stream()
                .collect(Collectors.toMap(SceneProjectEntity::getProjectName, SceneProjectEntity::getId, (t1, t2) -> t1));

        // 大于当天的数据
        dataSet = Joins.of(CarbonSinkDataEntity.class)
                .selectAll()
                .leftJoin(SceneProjectEntity.class, SceneProjectEntity::getId, CarbonSinkDataEntity::getSceneProjectId)
                .select(SceneProjectEntity::getProjectName)
                .end()
                .gt(CarbonSinkDataEntity::getSolidifyDate, Y666Utils.formatYyyyMmDd(new Date()))
                .joinList(CarbonSinkDataResp.class).stream().map(t -> key(t.getType(), t.getSolidifyDate(), t.getProjectName())).collect(Collectors.toSet());

    }

    private String key(String type, Date date, String projectName) {
        return type + "::" + Y666Utils.formatYyyyMmDd(date) + "::" + projectName;
    }

    @Override
    public void verify(CarbonSinkDataExtEntity entity) {
        addErrorMsg(entity.getSolidifyDate() == null, "数据时间不能为空！");
        addErrorMsg(entity.getSolidifyDate() != null && entity.getSolidifyDate().before(DateUtil.endOfDay(DateUtil.date())), "数据时间必须大于当天！");
        addErrorMsg(StringUtils.isEmpty(entity.getProjectName()), "所属项目名称不能为空！");
        addErrorMsg(StringUtils.isNotEmpty(entity.getProjectName()) && !projectMap.containsKey(entity.getProjectName()), "所属项目【" + entity.getProjectName() + "】不存在！");
        addErrorMsg(StringUtils.isEmpty(entity.getType()), "植被类型不能为空！");
//        addErrorMsg(StringUtils.isNotEmpty(entity.getType()) && !DictHelper.i().existV(ICarbonSinkDataFilter.CARBON_SINK_DATA_TYPE, entity.getType()) , "植被类型不存在！");
        addErrorMsg(entity.getArea() == null, "面积不能为空！");
        String key = key(entity.getType(), entity.getSolidifyDate(), entity.getProjectName());
//        addErrorMsg(dataSet.contains(key), "数据时间【" + Y666Utils.formatYyyyMmDd(entity.getSolidifyDate()) + "】所属项目【" + entity.getProjectName() + "】植被类型【" + DictHelper.i().getLabel(ICarbonSinkDataFilter.CARBON_SINK_DATA_TYPE, entity.getType()) + "】, 数据已存在！");
        entity.setSceneProjectId(projectMap.get(entity.getProjectName()));
//        addErrorMsg(keySet.contains(key), "数据时间【" + Y666Utils.formatYyyyMmDd(entity.getSolidifyDate()) + "】所属项目【" + entity.getProjectName() + "】植被类型【" + DictHelper.i().getLabel(ICarbonSinkDataFilter.CARBON_SINK_DATA_TYPE, entity.getType()) + "】, 在导入文件中出现重复！");
        keySet.add(key);
    }

    private BigDecimal getFactor(String type, Date date) {
        factorMap.putIfAbsent(CarbonSinkFactorHelper.i().key(type, date), CarbonSinkFactorHelper.i().getCacheFactor(type, date));
        return factorMap.get(CarbonSinkFactorHelper.i().key(type, date));
    }

    @Override
    public int processAfter(List<CarbonSinkDataExtEntity> resultList) {
        if (CollectionUtils.isEmpty(resultList)) {
            return 0;
        }

        List<CarbonSinkDataEntity> list = new ArrayList<>();
        for (CarbonSinkDataExtEntity entity : resultList) {
            Pair<BigDecimal, String> pair = CarbonSinkFactorHelper.i().calcDay(getFactor(entity.getType(), entity.getSolidifyDate()), entity.getArea());
            entity.setCarbonEmission(pair.getKey());
            entity.setCarbonEmissionProcess(pair.getValue());
            list.add(entity);
        }
        carbonSinkDataService.saveBatch(list, BATCH_SIZE);
        return list.size();
    }

}
